﻿/*
 Copyright (c) 2010 Rob Lieving, Adeptyx Consulting

 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
 files (the "Software"), to deal in the Software without
 restriction, including without limitation the rights to use,
 copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following
 conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
*/

/*globals Ext */

"use strict";

Ext.namespace("Ext.net");

Ext.net.Store = Ext.extend(Ext.data.Store, {

    constructor: function (config) {
    
        var cn,         // connection
            s = this;   // store object
    
        // apply the store constructor
        Ext.net.Store.superclass.constructor.call(this, config);
        
        // cached the connection
        cn = this.proxy.getConnection();
        
        // register the request complete event the first time
        cn.on({
            
            // intercept the xml data before getting delivered to the store and parse it
            'requestcomplete': {
            
                fn: function (cn, r, opts) {
                
                        // the document element from the response
                    var d = r.responseXML.documentElement,
                    
                        // the table elements of a Microsoft SOAP call
                        tblEls = d.getElementsByTagName("xs:element/xs:complexType/xs:choice/xs:element"),
                    
                        TableDef = function (el) {
                        
                            // back to this table
                            var t = this,
                            
                            // translation for xml data types to Ext field data types
                            getDataType = 
                    
                                function (attr) {
            
                                    switch (attr) {

                                    case 'xs:string':
                                        return 'string';

                                    case 'xs:date':
                                    case 'xs:dateTime':
                                    case 'xs:time':
                                        return 'date';

                                    case 'xs:boolean':
                                        return 'boolean';
                                                    
                                    case 'xs:byte':
                                    case 'xs:int':
                                    case 'xs:long':
                                    case 'xs:short':
                                        return 'int';
                                        
                                    case 'xs:decimal':
                                        return 'float';    
                                    }    
                                    
                                    return 'string';
                                },
                                
                            addFields = function (els) {
                            
                                var i;
                                for (i = 0; i < els.length; i = i + 1) {
                                    t.fields.push(
                                        {
                                            name: els[i].getAttribute('name'),
                                            type: getDataType(els[i].getAttribute('type'))
                                        }
                                    );
                                }
                            };
                            
                            // the name of the table - will be the id
                            this.name = el.getAttribute('name');        
                            
                            // the field array
                            this.fields = [];
                            
                            // adds fields to the table
                            addFields(el.getElementsByTagName('xs:complexType/xs:sequence/xs:element'));
                        },
                        // returns a table object from the xml passed here
                        getTable = function (nm) {
                            var i, e;
                            for (i = 0; i < tblEls.length; i = i + 1) {
                                e = tblEls[i];
                                if (e.getAttribute('name') === nm) {
                                    return new TableDef(e);
                                }                           
                            }
                        },
                            // data table definition
                        dTbl, 
                        // loop
                        i;
                    
                    // check for config.net and create table by name
                    if (config.net && config.net.dataTable) {
                        dTbl = getTable(config.net.dataTable);
                    } else {
                       // if omitted, then the first table is created from the xml
                        dTbl = new TableDef(tblEls[0]);
                    }
                    
                    // create a new data reader, using the cached data as the table definition
                    s.reader = new Ext.data.XmlReader({
                        id: dTbl.fields[0].name,
                        record: dTbl.name
                    },
                        dTbl.fields
                    );    
                    
                    // only fire the add event once and then delete from the queue
                    s.on({
                        'add': {
                            fn: function (t, recs, idx) {
                                
                                var tRecs,  // total records table
                                    path,   // path to the total records
                                    tNum;   // total number
                                
                                // if totalRecords passed, update the store and reader accordingly
                                if (config.net && config.net.totalRecords) {
                                    // get the name of the total records table
                                    tRecs = getTable(config.net.totalRecords);
                                    // create the path to the total records table
                                    path = tRecs.name + '/' + tRecs.fields[0].name;
                                    // set the path to the reader
                                    s.reader.meta.totalRecords = path;
                                    // get the number of records for paging
                                    tNum = new Number(d.getElementsByTagName(path)[0].firstChild.nodeValue);
                                    // set the store TotalLength value for the pager
                                    s.totalLength =  tNum.valueOf();
                                }
                                // data loaded - fire the loaded event
                                s.fireEvent('load');
                            },
                            // remove the 'add' event from the queue
                            single: true
                        }
                    });
                
                    // read the locally cached records into the store
                    s.add(s.reader.readRecords(r.responseXML).records);
                    
                },
                // remove the requestcomplete from the queue
                single: true
            }
        });
    }
});
